
/**
 * 
 */
package cz.cuni.mff.abacs.burglar.logics.storage;

import cz.cuni.mff.abacs.burglar.logics.objects.BaseObject;
import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;


/** 
 * Abstract base of the loader and slaver classes.
 * 
 * Static class.
 * 
 * Implements useful XML related functions and contains string constants and.
 * 
 * @author abacs
 *
 */
public abstract class XMLBase {
	
	// static properties:
	
	public static final String STR_MAP         = "map";
	public static final String STR_ROOM        = "room";
	public static final String STR_CAMERA      = "camera";
	public static final String STR_CONTAINER   = "container";
	public static final String STR_DOG         = "dog";
	public static final String STR_DOOR        = "door";
	public static final String STR_FLOOR       = "floor";
	public static final String STR_PHONE       = "phone";
	public static final String STR_SWITCH      = "switc";
	public static final String STR_VENDER      = "vender";
	public static final String STR_BURGLAR     = "burglar";
	public static final String STR_GUARD       = "guard";
	public static final String STR_ID          = "id";
	public static final String STR_KEY         = "key";
	public static final String STR_LADDER      = "ladder";
	public static final String STR_TARGET      = "target";
	public static final String STR_TREASURE    = "treasure";
	public static final String STR_X           = "x";
	public static final String STR_Y           = "y";
	public static final String STR_WIDTH       = "width";
	public static final String STR_HEIGHT      = "height";
	public static final String STR_POSITION    = "position";
	public static final String STR_AIM         = "aim";
	public static final String STR_IN          = "in";
	public static final String STR_FROM_ROOM   = "from_room";
	public static final String STR_TO_ROOM     = "to_room";
	public static final String STR_IS_LIT      = "is_lit";
	public static final String STR_IS_ACTIVE   = "is_active";
	public static final String STR_IS_LOCKED   = "is_locked";
	public static final String STR_IS_CLOSED   = "is_closed";
	public static final String STR_IS_RINGING  = "is_ringing";
	public static final String STR_IS_STUNNED  = "is_stunned";
	public static final String STR_HAS_DROPPED = "has_dropped";
	public static final String STR_COLLECT     = "collect";
	public static final String STR_KNOWLEDGE   = "knowledge";
	public static final String STR_INVENTORY   = "inventory";
	public static final String STR_TRAP_COUNT  = "trap_count";
	public static final String STR_GOAL        = "goal";
	public static final String STR_BELIEFBASE  = "belief_base";
	public static final String STR_NOTES       = "notes";
	public static final String STR_NOTE        = "note";
	
	public static final String STR_PATH     = "path";
	
	
	// -------------------------------------------------------------------------
	// constructors:
	
	
	/**
	 * Protected constructor to prevent object creation.
	 */
	protected XMLBase() {  }
	
	
	// -------------------------------------------------------------------------
	// implementation:
	
	
	/** 
	 * Builds a document tree 
	 * 
	 * @param fileName name of the file to parse the tree from.
	 * @return the resulted document tree, or null.
	 * */
	protected static Document parseXmlFile(String fileName) {
		// get the factory
		DocumentBuilderFactory builderFactory = 
			DocumentBuilderFactory.newInstance();
		Document ret;
		try{
			// Using factory get an instance of document builder
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			// parse using builder to get DOM representation of the XML file
			ret = builder.parse(fileName);
		}catch(ParserConfigurationException pce){
			pce.printStackTrace();
			return null;
		}catch(SAXException se){
			se.printStackTrace();
			return null;
		}catch(IOException ioe){
			ioe.printStackTrace();
			return null;
		}
		return ret;
	}
	
	
	/** 
	 * Builds a document tree 
	 * 
	 * @param iStream input stream to parse the tree from.
	 * @return the resulted document tree, or null.
	 * */
	protected static Document parseXmlStream(InputStream iStream) {
		// get the factory
		DocumentBuilderFactory builderFactory = 
			DocumentBuilderFactory.newInstance();
		Document ret = null;
		try{
			// Using factory get an instance of document builder
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			// parse using builder to get DOM representation of the XML file
			ret = builder.parse(iStream);
		}catch(ParserConfigurationException pce){
			pce.printStackTrace();
			return null;
		}catch(SAXException se){
			se.printStackTrace();
			return null;
		}catch(IOException ioe){
			ioe.printStackTrace();
			return null;
		}
		return ret;
	}
	
	
	/** 
	 * Writes a string into a file and closes it.
	 * The file gets rewritten.
	 * 
	 * @param text text to write into the file.
	 * @param fileName The name of the file to write into.
	 */
	protected static void writeToFile(String text, String fileName) {
		// write to the file:
		try{
			// Create file 
			FileWriter fstream = new FileWriter(fileName);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(text);
			// Close the output stream
			out.close();
		}catch(Exception e){	// Catch exception if any
			System.err.println(e.getMessage());
		}
	}
	
	
	/** 
	 * Writes a string into a stream and flushes it.
	 * 
	 * @param text text to write into the file.
	 * @param outstream The opened stream to write into.
	 */
	protected static void writeToStream(String text, OutputStream outstream) {
		// write to the file:
		try{
			// Create writer 
			OutputStreamWriter out = new OutputStreamWriter(outstream);
			
			out.write(text);
			// Close the output stream
			out.flush();
		}catch(Exception e){	// Catch exception if any
			System.err.println(e.getMessage());
		}
	}
	
	
	// -------------------------------------------------------------------------
	
	
	/** 
	 * Returns the integer interpretation of a tag in an XML element.
	 * If it can't be interpreted as an integer, returns 0.
	 * 
	 * @param element element to get the tag from.
	 * @param tag tag of the element to interpret.
	 * @return the integer value, or 0.
	 */
	protected static int getIntAttrOrZero(Element element, String tag){
		int ret;
		try{
			ret = Integer.parseInt(element.getAttribute(tag));
		}catch(NumberFormatException e){ 
			ret = 0;
		}
		return ret;
	}
	
	
	/** 
	 * Returns the integer interpretation of a tag in an XML element.
	 * If it can't be interpreted as an integer, returns the defaultValue.
	 * 
	 * @param element element to get the tag from.
	 * @param tag tag of the element to interpret.
	 * @param defaultValue value to use if the tag's text is not 
	 *                     a valid integer.
	 * @return the integer value, or defaultValue.
	 */
	protected static int getIntAttrOrDefault(
			Element element,
			String tag,
			int defaultValue
	){
		int ret;
		try{
			ret = Integer.parseInt(element.getAttribute(tag));
		}catch(NumberFormatException e){ 
			ret = defaultValue;
		}
		return ret;
	}
	
	
	/** 
	 * Returns the boolean interpretation of a tag in an XML element.
	 * If it can't be interpreted as a boolean, returns false.
	 * 
	 * @param element element to get the tag from.
	 * @param tag tag of the element to interpret.
	 * @return the boolean value, or false.
	 */
	protected static boolean getBooleanAttrOrFalse(Element element, String tag) {
		boolean ret;
		try{
			ret = Boolean.parseBoolean(element.getAttribute(tag));
		}catch(NumberFormatException e){ 
			ret = false;
		}
		return ret;
	}
	
	
	/** 
	 * Returns the boolean interpretation of a tag in an XML element.
	 * If it can't be interpreted as a boolean, returns the defaultValue.
	 * 
	 * @param element element to get the tag from.
	 * @param tag tag of the element to interpret.
	 * @param defaultValue value to use if the tag's text is not 
	 *                     a valid boolean.
	 * @return the boolean value, or defaultValue.
	 */
	protected static boolean getBooleanAttrOrTrue(Element element, String tag) {
		boolean ret;
		try{
			ret = Boolean.parseBoolean(element.getAttribute(tag));
		}catch(NumberFormatException e){ 
			ret = true;
		}
		return ret;
	}
	
	
	/**
	 * Converts object types to string format.
	 */
	public static String typeToString(BaseObject.Type type) {
		switch(type){
		case BURGLAR:
			return XMLLoader.STR_BURGLAR;
		case DOG:
			return XMLBase.STR_DOG;
		case GUARD:
			return XMLBase.STR_GUARD;
		case KEY:
			return XMLBase.STR_KEY;
		case LADDER:
			return XMLBase.STR_LADDER;
		case TREASURE:
			return XMLBase.STR_TREASURE;
		case CAMERA:
			return XMLBase.STR_CAMERA;
		case CONTAINER:
			return XMLBase.STR_CONTAINER;
		case DOOR:
			return XMLBase.STR_DOOR;
		case FLOOR:
			return XMLBase.STR_FLOOR;
		case PHONE:
			return XMLBase.STR_PHONE;
		case SWITCH:
			return XMLBase.STR_SWITCH;
		case VENDER:
			return XMLBase.STR_VENDER;
		default:
			return "";
		}
	}

}
